package com.airticketbooking.service.serviceImpl;

import com.airticketbooking.common.constant.LevelConstant;
import com.airticketbooking.common.constant.StatusConstant;
import com.airticketbooking.mapper.*;
import com.airticketbooking.po.*;
import com.airticketbooking.service.PaymentService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author Mr.J
 * @version 1.0.0
 * @date 2024/11/13
 * @desc
 */
@Service

@RequiredArgsConstructor
public class PaymentServiceImpl implements PaymentService {

	private final OrderMapper orderMapper;

	private final PaymentMapper paymentMapper;

	private final UserMapper userMapper;

	private final PointMapper pointMapper;

	private final MemberMapper memberMapper;
	private final OrderWithTicketMapper orderWithTicketMapper;
	private final TicketMapper ticketMapper;


	@Override
	@Transactional  // 确保事务管理
	public void createPaymentByOrderId(Integer orderId) {
		// 根据orderId获取需要支付的金额

		Payment paymentById = paymentMapper.getPaymentById(orderId);

		if (paymentById != null) {
			throw new IllegalArgumentException("订单已支付,无法重复支付");
		}


		Order order = orderMapper.getOrderById(orderId);

		if (order.getStatus() != StatusConstant.ORDER_CONFIRMED) {
			throw new IllegalArgumentException("订单状态不正确，无法支付");
		}

		if (order == null) {
			throw new IllegalArgumentException("Order not found for orderId: " + orderId);
		}
		// 通过orderId获取用户信息
		User user = userMapper.getUserById(order.getUserId());
		if (user == null) {
			throw new IllegalArgumentException("User not found for userId: " + order.getUserId());
		}

		// 实现支付创建
		Payment payment = new Payment();
		payment.setOrderId(orderId);
		payment.setPayTypeId(1);
		payment.setPaymentDateTime(LocalDateTime.now());
		payment.setUpdateDateTime(LocalDateTime.now());
		payment.setPaymentAmount(order.getActualAmountDue());
		paymentMapper.createPayment(payment);

		// 更改订单状态为已支付
		order.setUpadateDateTime(LocalDateTime.now());
		order.setStatus(StatusConstant.PAID);
		orderMapper.modifyOrder(order);

//		更改票据状态为已支付
		List<Integer> ticketIds = orderWithTicketMapper.getTicketIdsByOrderId(orderId);

		for (Integer ticketId : ticketIds) {
			Ticket ticket = ticketMapper.getTicketById(ticketId);
			ticket.setStatus(StatusConstant.PAID);
			ticket.setPurchaseDate(LocalDateTime.now());
			ticket.setUpdateTime(LocalDateTime.now());
			ticketMapper.update(ticket);
		}


		// 更新用户余额
		updateUserAccountBalance(user, order.getActualAmountDue());

		// TODO 用websocket发送支付成功的邮件给用户

//		更新用户积分信息
		Member member = memberMapper.getByUserId(order.getUserId());
		if (member != null) {

			Point point = pointMapper.getPointByMemberId(member.getMemberId());

			Integer totalPoints = point.getTotalPoints();

			Integer newPoint = calculatePoints(order.getActualAmountDue());
			totalPoints -= order.getDiscountPoint();  // 注意：DiscountPoint应准确对应订单中折扣的积分
			totalPoints += newPoint;

			// 更新用户积分信息
			point.setTotalPoints(totalPoints);
			pointMapper.ModifyPoint(point.getPointId(), totalPoints); // 保存更新

			//跟新订单中的获得积分
			order.setEarnedPoints(newPoint);
			orderMapper.modifyOrder(order);


			// 更新会员等级
			Integer newLevel = updateMemberLevel(totalPoints);
			memberMapper.ModifyLevel(member.getMemberId(), newLevel);
		}


	}

	private void updateUserAccountBalance(User user, BigDecimal amount) {
		BigDecimal accountBalance = user.getAccountBalance();
		if (accountBalance.compareTo(amount) < 0)
			throw new IllegalArgumentException("余额不足,无法支付"); // 检查是否有足够余额
		accountBalance = accountBalance.subtract(amount);
		user.setAccountBalance(accountBalance);
		user.setUpdateDate(LocalDateTime.now());
		userMapper.update(user);
	}

	private Integer calculatePoints(BigDecimal actualAmountDue) {
		if (actualAmountDue.compareTo(BigDecimal.ZERO) < 0) return 0; // 负数支付不计算积分
		return actualAmountDue.divide(BigDecimal.valueOf(100)).intValue() * 5; // 每100元可获得5点积分
	}

	private Integer updateMemberLevel(Integer totalPoints) {
		// 会员等级规则，可以「提取成常量避免魔法数字」
		if (totalPoints >= 2000) {
			return LevelConstant.VVIP; // 升级为VVIP
		} else if (totalPoints >= 1000) {
			return LevelConstant.SVIP; // 升级为SVIP
		}
		return LevelConstant.VIP; // 默认VIP
	}

}

